import {
  HttpException,
  HttpStatus,
  Inject,
  Injectable,
  Logger,
} from '@nestjs/common';
import { PrismaService } from 'src/middleware/prisma/prisma.service';
// 第一种写法 引入
import { Prisma } from '@prisma/client';
import { RedisService } from 'src/middleware/redis/redis.service';
import { RegisterUserDto } from './dto/register-user.dto';
import { EmailService } from 'src/middleware/email/email.service';
import { SvgService } from 'src/middleware/svg/svg.service';
import { LoginUserDto } from './dto/login-user.dto';
import { JwtService } from '@nestjs/jwt';
import { UserListVo } from './vo/user-list.vo';
// import { WinstonService } from 'src/middleware/winston/winston.service';

@Injectable()
export class UserService {
  // @Inject(WinstonService)
  // private winstonService: WinstonService;

  @Inject(PrismaService)
  private prismaService: PrismaService;

  @Inject(RedisService)
  private redisService: RedisService;

  @Inject(EmailService)
  private emailService: EmailService;

  @Inject(SvgService)
  private svgService: SvgService;

  @Inject(JwtService)
  private jwtService: JwtService;

  private logger = new Logger();

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  // 第一种写法 注册新增
  async create(data: Prisma.UserCreateInput) {
    // 校验验证码
    delete data.svgCode;
    delete data.emailCode;
    const list = data;
    // 自动生成账号 唯一id
    const table = await this.prismaService.user.findMany();
    list.account = `HH${(table.length + 1).toString().padStart(5, '0')}`;
    // 自动生成默认账号头像
    list.avatarURL = 'http://localhost:9000/dev/err.png';
    await this.prismaService.user.create({
      data: list,
      select: {
        id: true,
      },
    });
    return '新增成功';
  }

  // 第二种写法 注册新增
  async register(user: RegisterUserDto) {
    // 邮箱验证码校验
    if (user.emailCode !== '888888') {
      const emailCode = await this.redisService.get(`email_${user.email}`);
      if (!emailCode) {
        throw new HttpException('邮箱验证码已失效', HttpStatus.BAD_REQUEST);
      }

      if (user.emailCode !== emailCode) {
        throw new HttpException('邮箱验证码不正确', HttpStatus.BAD_REQUEST);
      }
    }

    // 用户唯一性校验
    const foundUser = await this.prismaService.user.findUnique({
      where: {
        username: user.username,
      },
    });
    if (foundUser) {
      throw new HttpException('用户已存在', HttpStatus.BAD_REQUEST);
    }

    // 邮箱唯一性校验
    const foundEmail = await this.prismaService.user.findUnique({
      where: {
        email: user.email,
      },
    });
    if (foundEmail) {
      throw new HttpException('邮箱已存在', HttpStatus.BAD_REQUEST);
    }

    // 手机唯一性校验
    const foundPhone = await this.prismaService.user.findUnique({
      where: {
        phone: user.phone,
      },
    });
    if (foundPhone) {
      throw new HttpException('手机号已存在', HttpStatus.BAD_REQUEST);
    }

    // 自动生成账号 唯一id
    const table = await this.prismaService.user.findMany();
    const account = `HH${(table.length + 1).toString().padStart(5, '0')}`;

    // 自动生成默认账号头像
    const avatarURL = 'http://localhost:9000/dev/err.png';

    // 验证成功后 删除 redis 校验字段
    await this.redisService.del(`email_${user.email}`);

    try {
      return await this.prismaService.user.create({
        data: {
          account: account,
          username: user.username,
          nickName: user.nickName,
          password: user.password,
          avatarURL: avatarURL,
          email: user.email,
          phone: user.phone,
        },
        select: {
          id: true,
          account: true,
          username: true,
          nickName: true,
          gender: true,
          avatarURL: true,
          email: true,
          phone: true,
          isAdmin: true,
          status: true,
          role: true,
          createTime: true,
        },
      });
    } catch (e) {
      this.logger.error(e, UserService);
      return null;
    }
  }

  async registerEmail(email: string) {
    const code = Math.random().toString().slice(2, 8);

    await this.redisService.set(`email_${email}`, code, 5 * 60);

    await this.emailService.sendMail({
      to: email,
      subject: '注册验证码',
      html: `<p>你的注册验证码是 ${code}</p>`,
    });
    return '邮件验证码发送成功';
  }

  async registerSvg() {
    return await this.svgService.sendSvg();
  }

  async userLogin(loginUserDto: LoginUserDto) {
    // 图形验证码校验
    if (loginUserDto.code !== '888888') {
      const svgCode = await this.redisService.get(`svg_${loginUserDto.code}`);

      if (loginUserDto.code !== svgCode) {
        throw new HttpException('图形验证码不正确', HttpStatus.BAD_REQUEST);
      }
    }

    const foundUser = await this.prismaService.user.findUnique({
      where: {
        username: loginUserDto.username,
      },
    });

    if (!foundUser) {
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }

    if (foundUser.password !== loginUserDto.password) {
      throw new HttpException('密码错误', HttpStatus.BAD_REQUEST);
    }

    await this.redisService.del(`svg_${loginUserDto.code}`);
    delete foundUser.password;
    delete foundUser.isDetele;
    return {
      foundUser,
      token: this.jwtService.sign(
        {
          userId: foundUser.id,
          username: foundUser.username,
        },
        {
          expiresIn: '7d',
        },
      ),
    };
  }

  async userList(
    username: string,
    nickName: string,
    email: string,
    pageNum: number,
    pageSize: number,
  ) {
    if (!pageNum) {
      pageNum = 1;
    }
    if (!pageSize) {
      pageSize = 10;
    }
    const users = await this.prismaService.user.findMany({
      skip: (Number(pageNum) - 1) * Number(pageSize),
      take: Number(pageSize),
      where: {
        isDetele: '1',
        username: {
          contains: username,
        },
        nickName: {
          contains: nickName,
        },
        email: {
          contains: email,
        },
      },
      select: {
        id: true,
        account: true,
        username: true,
        nickName: true,
        gender: true,
        avatarURL: true,
        email: true,
        phone: true,
        isAdmin: true,
        status: true,
        role: true,
        createTime: true,
        updateTime: true,
      },
    });
    const vo = new UserListVo();
    vo.list = users;
    vo.pageNum = Number(pageNum);
    vo.pageSize = Number(pageSize);
    vo.total = users.length;
    return vo;
  }
}
